using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace KaroGame.FrontEnd
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class WaitForTurnAnimation : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private KaroGame baseGame;

        private SpriteBatch spriteBatch;
        private SpriteFont font;

        private Model waitModel;

        private Matrix world;
        private Matrix view;
        private Matrix projection;
        private Matrix arrowRotation;

        private int rotate;

        private bool isActive;

        public bool IsActive
        {
            get { return isActive; }
            set { isActive = value; }
        }

        public WaitForTurnAnimation(Game game)
            : base(game)
        {
            baseGame = game as KaroGame;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            world = Matrix.CreateRotationY(MathHelper.ToRadians(65)) * Matrix.CreateRotationX(MathHelper.ToRadians(65))  * Matrix.CreateScale(0.01f);
            view = Matrix.CreateLookAt(new Vector3(0, 0, 4), Vector3.Zero, Vector3.Up);
            projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), (float)baseGame.Window.ClientBounds.Width / (float)baseGame.Window.ClientBounds.Height, 0.1f, 1000.0f);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(baseGame.GraphicsDevice);

            waitModel = baseGame.Content.Load<Model>("ArrowSphere");
            font = baseGame.Content.Load<SpriteFont>("Font/MenuHeader");
            
            base.LoadContent();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            DebugController.AddDebugAnimationOrErrorInfo( ( isActive ? "W" : "Not w" ) + "aiting for other players turn" );

            if (isActive)
            {
                if (rotate < 360)
                {
                    rotate += 2;
                }
                else
                {
                    rotate = 0;
                }

                arrowRotation = Matrix.CreateRotationZ(MathHelper.ToRadians(rotate));
            }

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            if (isActive)
            {
                //GraphicsDevice.RenderState.DepthBufferEnable = true;
                
                Matrix[] transforms = new Matrix[ waitModel.Bones.Count ];
                waitModel.CopyAbsoluteBoneTransformsTo(transforms);

                foreach (ModelMesh mesh in waitModel.Meshes)
                {
                    if (mesh.ParentBone.Name.Equals("Box001") || mesh.ParentBone.Name.Equals("Pyramid001"))
                    {
                        for (int i = 1; i <= 3; i++)
                        {
                            Matrix createExtraArrow = Matrix.CreateRotationY(MathHelper.ToRadians(120 * i));

                            foreach (BasicEffect effect in mesh.Effects)
                            {
                                effect.World = transforms[mesh.ParentBone.Index] * arrowRotation * createExtraArrow * world;
                                effect.View = view;
                                effect.Projection = projection;

                                effect.PreferPerPixelLighting = true;
                                effect.DiffuseColor = new Vector3(0, 0.6f, 0);

                                effect.EnableDefaultLighting();
                            }

                            mesh.Draw();
                        }
                    }
                    else
                    {
                        foreach (BasicEffect effect in mesh.Effects)
                        {
                            effect.World = transforms[mesh.ParentBone.Index] * world;
                            effect.View = view;
                            effect.Projection = projection;

                            effect.PreferPerPixelLighting = true;
                            effect.DiffuseColor = new Vector3(0, 0, 0.6f);

                            effect.EnableDefaultLighting();
                        }

                        mesh.Draw();
                    }
                }

                string text = "Waiting...";
                int x = (int)((SettingsManager.Instance.ResolutionWidth / 2) - (font.MeasureString(text).X / 2));
                int y = (int)((SettingsManager.Instance.ResolutionHeight / 2) - (font.MeasureString(text).Y / 2));

                spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Deferred, SaveStateMode.SaveState);
                spriteBatch.DrawString(font, text, new Vector2(x, y), Color.Beige);
                spriteBatch.End();
            }

            base.Draw(gameTime);
        }
    }
}